/******************************************************************************
秋夜静，独坐对残灯。
啼笑非非谁识我，坐行梦梦尽缘君，何所慰消沉。
风卷雨，雨复卷侬心。
心似欲随风雨去，茫茫大海任浮沉。
无爱亦无恨。
******************************************************************************/
#include "kbRGB_Int.h"
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "kbRGB_Int_Effect.h"

/*************************************************************************************************\
|        Bloom [9]                                                                                |
\*************************************************************************************************/
static void Bloom_UpdateFlowers(struct kbRGB_Flower flowers[], const uint16_t len_max, const unsigned int FPS, const unsigned int Speed)
{
    //float delta = (float) kbRGB_Speed / (float) kbRGB_FPS;

    for(unsigned int i = 0; i < (len_max); i++)
    {
        struct kbRGB_Flower* flower = &flowers[i];
        //flower->hue += (flower->speed_mult * delta);
        flower->hue += (flower->speed_mult * Speed/FPS);
        //flower->hsv.hue = (int) flower->hue % 360;
    }
}
static void Bloom_Reset(struct kbRGB_Flower flowers[], const uint16_t len_max)
{
    memset(flowers, 0x000, sizeof(struct kbRGB_Flower)*len_max);
    for(unsigned int i = 0; i < (len_max); i++)
    {
        struct kbRGB_Flower* flower = &flowers[i];
        flower->hue = (kb_rand() % 360)<<kbRGB_PRE_BIT;
        flower->speed_mult = (kb_rand()&kbRGB_PRE_MAX) + kbRGB_PRE_MAX;
    }
}
void kbRGB_Int_Bloom_Init(struct kbRGB_Int_Params *const params)    // 花朵
{
    const uint16_t cols=KB_COLS;
    const uint16_t rows=KB_ROWS;
    const uint16_t len_max = cols*rows;
    params->Speed = 50;
    params->Slider2Val = 30;
    Bloom_Reset(params->Random_flowers, len_max);
}
void kbRGB_Int_Bloom(const uint16_t cols, const uint16_t rows, const uint8_t speed, const int reverse, struct kbRGB_Int_Params *const params)    // 花朵
{
    const uint16_t len_max = cols*rows;
    hsv_t hsv;
    hsv.saturation = 255;
    hsv.value = 255;

    Bloom_UpdateFlowers(params->Random_flowers, len_max, params->FPS, params->Speed);
    for (uint16_t col_id = 0; col_id < cols; col_id++)
    {
        for (uint16_t row_id = 0; row_id < rows; row_id++)
        {
           int idx = (row_id * cols) + col_id;
           hsv.hue = (params->Random_flowers[idx].hue>>kbRGB_PRE_BIT) % 360;
           uint32_t color = hsv2rgb(&hsv);
           kbRGB_pset(col_id, row_id, color);
        }
    }
}

/*************************************************************************************************\
|        Lightning [9]                                                                              |
\*************************************************************************************************/
enum lightning_mode_value
{
    WHOLE_ZONE  = 0,
    PER_LED     = 1
};

void kbRGB_Int_Lightning_Init(struct kbRGB_Int_Params *const params)    // 闪电
{
    params->Speed = 20;
    params->Slider2Val = 10;
    memset(&params->Random_Lightning.Lightnings, 0x00, sizeof(params->Random_Lightning.Lightnings));
    params->Random_Lightning.mode = PER_LED;
}
static uint32_t Lightning_TriggerLightning(const int n, const uint16_t len_max, const uint32_t lightning_mode, struct kbRGB_Lightning_t Lightnings[], const unsigned int FPS, const unsigned int Speed, const unsigned int Slider2Val)
{
    const int Decay = Slider2Val;
    uint16_t index=0;
    uint16_t id;

    //float decrease = 1 + Decay/(float) FPS;

    //unsigned int mod = (lightning_mode == WHOLE_ZONE) ? 1000 : 1000 * 41*41;//z->leds_count();
    unsigned int mod = (lightning_mode == WHOLE_ZONE) ? 900 : 900 * len_max;//z->leds_count();

    id = n+1;
    for(index=0; index<LightningsSizeMax; index++)
    {
        // Serach
        if(id==Lightnings[index].id) break;
    }
    if(WHOLE_ZONE==lightning_mode) index = 0;
    if(index<LightningsSizeMax)
    {
        //printf("[%s--%d] index:%3d n:%3d", __func__, __LINE__, index, n);
        //fflush(stdout);
        //    Lightnings[n].value = ((unsigned int)(kb_rand() % mod)) < kbrgb_Params.Speed ?
        //                std::min<unsigned char>(255, RandomColorsEnabled ? 255: UserHSV.value) :
        //                Lightnings[z][n].value > 0 ?  Lightnings[z][n].value / decrease : 0;
//            Lightnings[index].hsv.value = ((unsigned int)(kb_rand() % mod)) < Speed ?
//                        255 : Lightnings[index].hsv.value > 0 ?  Lightnings[index].hsv.value / decrease : 0;
        Lightnings[index].hsv.value = ((unsigned int)(kb_rand() % mod)) < Speed ?
                    255 : Lightnings[index].hsv.value > 0 ?  (Lightnings[index].hsv.value*FPS) / (FPS + Decay) : 0;

            if(Lightnings[index].hsv.value == 0)
            {
                Lightnings[index].id = 0;
            }

            return (hsv2rgb(&Lightnings[index].hsv));
    }
    if(0==(kb_rand() % (20*len_max)))
    {
        for(index=0; index<LightningsSizeMax; index++)
        {
            // Empty
            if(0==Lightnings[index].id)
            {
                Lightnings[index].hsv.value = 255;
                Lightnings[index].hsv.hue = kb_rand() % 360;
                Lightnings[index].hsv.saturation = kb_rand() % 255;
                Lightnings[index].id = kb_rand() % len_max;
                break;
            }
        }
    }
    hsv_t hsv;
    hsv.hue = 0;
    hsv.saturation = 0;
    hsv.value = 0;
    //return 0x00;
    return (hsv2rgb(&hsv));
}

void kbRGB_Int_Lightning(const uint16_t cols, const uint16_t rows, const uint8_t speed, const int reverse, struct kbRGB_Int_Params *const params)    // 闪电
{
    const uint16_t len_max = cols*rows;
    const uint32_t mode = params->Random_Lightning.mode;
    if(mode == WHOLE_ZONE)
    {
        uint32_t color = Lightning_TriggerLightning(0, 1, mode, params->Random_Lightning.Lightnings, params->FPS, params->Speed, params->Slider2Val);
        for (uint16_t col_id = 0; col_id < cols; col_id++)
        {
            for (uint16_t row_id = 0; row_id < rows; row_id++)
            {
               kbRGB_pset(col_id, row_id, color);
            }
        }
    }
    else if(mode == PER_LED)
    {
        for (uint16_t col_id = 0; col_id < cols; col_id++)
        {
            for (uint16_t row_id = 0; row_id < rows; row_id++)
            {
                uint16_t id = row_id*cols+col_id;
                uint32_t color = Lightning_TriggerLightning(id, len_max, mode, params->Random_Lightning.Lightnings, params->FPS, params->Speed, params->Slider2Val);
                kbRGB_pset(col_id, row_id, color);
            }
        }
    }
}
